﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.IO;
using Microsoft.Xna.Framework.Content;
using DARE.Properties;

namespace DARE
{
    public class CBasicEffect
    {
        #region fields

        #region CONST

        public const string ANIMATIONVARIABLE = "Bones";
        public const string ANIMATIONENABLED = "animationEnabled";

        public const string DEFAULTEFFECT = "Shaders\\IntensityEffect";
        public const string DEFAULTTECHNIQUE = "SpecularLight";

        public const string WORLDINVERSE = "matWorldInverse";
        public const string WORLD = "matWorld";
        public const string WORLDVIEWPROJECTION = "matWorldViewProj";
        public const string LIGHTWORLDVIEWPROJECTION = "matLightWorldViewProj";
        public const string DECALSPROJECTORMATRIX = "decalsProjectorMatrix";

        public const string DECALSENABLED = "decalsEnabled";
        public const string DECALSMAP = "DecalsMap";

        public const string POSEYE = "posEye";
        public const string VECLIGHTPOS = "vecLightPos";

        public const string FOGCOLOR = "fogColor";
        public const string FOGNEAR = "fogNear";
        public const string FOGFAR = "fogFar";
        public const string FOGENABLED = "fogEnabled";

        public const string HIGHLIGHTINTENSITY = "highlightIntensity";
        public const string SPECULARCOLOR = "specularColor";
        public const string SPECULARINTENSITY = "specularIntensity";
        public const string BRIGHTNESS = "brightness";
        public const string DIFFUSECOLOR = "diffuseColor";
        public const string DIFFUSEINTENSITY = "diffuseIntensity";
        public const string AMBIENTCOLOR = "ambientColor";
        public const string AMBIENTINTENSITY = "ambientIntensity";
        public const string NORMALMAP = "NormalMap";
        public const string SPECULARMAPENABLED = "specularMapEnabled";
        public const string SPECULARMAP = "SpecularMap";

        public const string COLORMAP = "ColorMap";
        #endregion

        protected uint m_uniqueId;

        protected bool lighteningEnabled;
/*        protected Vector4 emissiveLight;
        protected Vector4 ambientLight;
        protected Vector3 directionalLight1Direction;
        protected Vector4 directionalLight1Diffuse;
        protected Vector4 directionalLight1Specular;
        protected Vector3 directionalLight2Direction;
        protected Vector4 directionalLight2Diffuse;
        protected Vector4 directionalLight2Specular;
        protected Vector3 DirectionalLight0Direction;
        protected Vector4 DirectionalLight0Diffuse;
        protected Vector4 DirectionalLight0Specular;*/
        protected Effect m_effect;
        protected string m_techniquePrefix = "";

        #endregion
                
        #region properties

        public Effect Effect { get { return m_effect; } }
        public string Name { get; set; }

/*        #region lightening

        public float Brighteness { get; set; }

        public bool LighteningEnabled { get { return lighteningEnabled; } set { lighteningEnabled = value; } }

        public Color AmbientLightColor
        {
            get
            {
                return new Color(ambientLight.X, ambientLight.Y, ambientLight.Z);
            }
            set
            {
                ambientLight.X = value.R;
                ambientLight.Y = value.G;
                ambientLight.Z = value.B;
            }
        }

        public float AmbientLightIntensity
        {
            get
            {
                return ambientLight.W;
            }
            set
            {
                ambientLight.W = value;
            }
        }

        public Color EmissiveLightColor
        {
            get
            {
                return new Color(emissiveLight.X, emissiveLight.Y, emissiveLight.Z);
            }
            set
            {
                emissiveLight.X = value.R;
                emissiveLight.Y = value.G;
                emissiveLight.Z = value.B;
            }
        }

        public float EmissiveLightIntensity
        {
            get
            {
                return emissiveLight.W;
            }
            set
            {
                emissiveLight.W = value;
            }
        }

        public Vector3 DirectionalLight1Direction
        {
            get { return directionalLight1Direction; }
            set { directionalLight1Direction = value; }
        }

        public Color DirectionalLight1DiffuseColor
        {
            get { return new Color(directionalLight1Diffuse.X, directionalLight1Diffuse.Y, directionalLight1Diffuse.Z); }
            set
            {
                directionalLight1Diffuse.X = value.R;
                directionalLight1Diffuse.Y = value.G;
                directionalLight1Diffuse.Z = value.B;
            }
        }

        public float DirectionalLight1DiffuseIntensity
        {
            get { return directionalLight1Diffuse.W; }
            set { directionalLight1Diffuse.W = value; }
        }

        public Color DirectionalLight1SpecularColor
        {
            get { return new Color(directionalLight1Specular.X, directionalLight1Specular.Y, directionalLight1Specular.Z); }
            set
            {
                directionalLight1Specular.X = value.R;
                directionalLight1Specular.Y = value.G;
                directionalLight1Specular.Z = value.B;
            }
        }

        public float DirectionalLight1SpecularIntensity
        {
            get { return directionalLight1Specular.W; }
            set { directionalLight1Specular.W = value; }
        }

        public Vector3 DirectionalLight2Direction
        {
            get { return directionalLight2Direction; }
            set { directionalLight2Direction = value; }
        }

        public Color DirectionalLight2DiffuseColor
        {
            get { return new Color(directionalLight2Diffuse.X, directionalLight2Diffuse.Y, directionalLight2Diffuse.Z); }
            set
            {
                directionalLight2Diffuse.X = value.R;
                directionalLight2Diffuse.Y = value.G;
                directionalLight2Diffuse.Z = value.B;
            }
        }

        public float DirectionalLight2DiffuseIntensity
        {
            get { return directionalLight2Diffuse.W; }
            set { directionalLight2Diffuse.W = value; }
        }

        public Color DirectionalLight2SpecularColor
        {
            get { return new Color(directionalLight2Specular.X, directionalLight2Specular.Y, directionalLight2Specular.Z); }
            set
            {
                directionalLight2Specular.X = value.R;
                directionalLight2Specular.Y = value.G;
                directionalLight2Specular.Z = value.B;
            }
        }

        public float DirectionalLight2SpecularIntensity
        {
            get { return directionalLight2Specular.W; }
            set { directionalLight2Specular.W = value; }
        }

        public Vector3 DirectionalLight0Direction
        {
            get { return DirectionalLight0Direction; }
            set { DirectionalLight0Direction = value; }
        }

        public Color DirectionalLight0DiffuseColor
        {
            get { return new Color(DirectionalLight0Diffuse.X, DirectionalLight0Diffuse.Y, DirectionalLight0Diffuse.Z); }
            set
            {
                DirectionalLight0Diffuse.X = value.R;
                DirectionalLight0Diffuse.Y = value.G;
                DirectionalLight0Diffuse.Z = value.B;
            }
        }

        public float DirectionalLight0DiffuseIntensity
        {
            get { return DirectionalLight0Diffuse.W; }
            set { DirectionalLight0Diffuse.W = value; }
        }

        public Color DirectionalLight0SpecularColor
        {
            get { return new Color(DirectionalLight0Specular.X, DirectionalLight0Specular.Y, DirectionalLight0Specular.Z); }
            set
            {
                DirectionalLight0Specular.X = value.R;
                DirectionalLight0Specular.Y = value.G;
                DirectionalLight0Specular.Z = value.B;
            }
        }

        public float DirectionalLight0SpecularIntensity
        {
            get { return DirectionalLight0Specular.W; }
            set { DirectionalLight0Specular.W = value; }
        }
        
        #endregion

        #region matrix

        public Matrix World
        {
            get;
            set;
        }

        public Matrix View
        {
            get;
            set;
        }

        public Matrix Projection
        {
            get;
            set;
        }

        public Matrix WorldView
        { get { return World * View; } }

        public Matrix ViewProjection
        { get { return View * Projection; } }

        public Matrix WorldViewProjection
        { get { return World * View * Projection; } }

        #endregion
   
        #region color

        public Texture2D ColorMap
        {
            get;
            set;
        }

        public float Alpha
        {
            get;
            set;
        }

        #endregion
        */
        #region Id

        public uint Id
        {
            get { return this.m_uniqueId; }
        }

        #endregion
        
        #endregion

        #region ctor

        /// <summary>
        /// Constructs the CBasicEffect class with a default effect file ("Shaders/IntensityEffect").
        /// If you want to use this ctor, you have to create this effect file at this path.
        /// You also have to implement a technique named "SpecularLight" which will be the default technique.
        /// If you don't want to, use the second ctor.
        /// </summary>
        /// <param name="content">The content manager you want to use for this effect</param>
        public CBasicEffect()
        {
            Name = "Shaders/BasicEffect";
            
#if WINDOWS_PHONE
            m_effect = new BasicEffect(DARE.CDare.Instance.GraphicsDevice);
#else

            m_effect = CResourceMgr.Load<Effect>(DARE.Properties.Resources.BasicEffect, Name);

            Initialize(m_techniquePrefix + "VertexLightBasic");
#endif       
        }
        
        #endregion

        #region Method

        protected void Initialize(string _defaultTechnique)
        {
            this.m_uniqueId = CEffectBank.RegisterShader(this);
            
            
        }

        public virtual CBasicEffect ProcessEffect(CRender3D render, CEffect effect)
        {

#if WINDOWS_PHONE
            BasicEffect e = m_effect as BasicEffect;
            e.EnableDefaultLighting();
            if (effect.UseSceneParameters)
            {
                e.PreferPerPixelLighting = render.EffectMgr.PerPixelLighteningEnabled;
                e.LightingEnabled = render.EffectMgr.LighteningEnabled;
            }
            else
            {
                e.PreferPerPixelLighting = effect.PerPixelLighteningEnabled;
                e.LightingEnabled = effect.LighteningEnabled;
            }
            e.View = effect.View;
            e.Projection = effect.Projection;
            e.World = effect.World;
            e.Texture = effect.ColorMap;
            e.TextureEnabled = true;
            e.Alpha = effect.Alpha;
            e.EmissiveColor = effect.EmissiveLightColor.ToVector3();
            
            e.SpecularPower = effect.Brighteness;
                
            if (effect.UseSceneParameters)
            {
                e.AmbientLightColor = render.EffectMgr.AmbientLightColor.ToVector3();
                e.DirectionalLight0.Direction = render.EffectMgr.DirectionalLight0Direction;
                e.DirectionalLight0.DiffuseColor = render.EffectMgr.DirectionalLight0DiffuseColor.ToVector3();
                e.DirectionalLight0.Enabled = render.EffectMgr.DirectionalLight0DiffuseIntensity > 0 ? true : false;
                e.DirectionalLight0.SpecularColor = render.EffectMgr.DirectionalLight0SpecularColor.ToVector3();

                e.DirectionalLight1.Direction = render.EffectMgr.DirectionalLight1Direction;
                e.DirectionalLight1.DiffuseColor = render.EffectMgr.DirectionalLight1DiffuseColor.ToVector3();
                e.DirectionalLight1.Enabled = render.EffectMgr.DirectionalLight1DiffuseIntensity > 0 ? true : false;
                e.DirectionalLight1.SpecularColor = render.EffectMgr.DirectionalLight1SpecularColor.ToVector3();

                e.DirectionalLight2.Direction = render.EffectMgr.DirectionalLight2Direction;
                e.DirectionalLight2.DiffuseColor = render.EffectMgr.DirectionalLight2DiffuseColor.ToVector3();
                e.DirectionalLight2.Enabled = render.EffectMgr.DirectionalLight2DiffuseIntensity > 0 ? true : false;
                e.DirectionalLight2.SpecularColor = render.EffectMgr.DirectionalLight2SpecularColor.ToVector3();

            }
            else
            {
                e.AmbientLightColor = effect.AmbientLightColor.ToVector3();
                e.DirectionalLight0.Direction = effect.DirectionalLight0Direction;
                e.DirectionalLight0.DiffuseColor = effect.DirectionalLight0DiffuseColor.ToVector3();
                e.DirectionalLight0.Enabled = effect.DirectionalLight0DiffuseIntensity > 0 ? true : false;
                e.DirectionalLight0.SpecularColor = effect.DirectionalLight0SpecularColor.ToVector3();

                e.DirectionalLight1.Direction = effect.DirectionalLight1Direction;
                e.DirectionalLight1.DiffuseColor = effect.DirectionalLight1DiffuseColor.ToVector3();
                e.DirectionalLight1.Enabled = effect.DirectionalLight1DiffuseIntensity > 0 ? true : false;
                e.DirectionalLight1.SpecularColor = effect.DirectionalLight1SpecularColor.ToVector3();

                e.DirectionalLight2.Direction = effect.DirectionalLight2Direction;
                e.DirectionalLight2.DiffuseColor = effect.DirectionalLight2DiffuseColor.ToVector3();
                e.DirectionalLight2.Enabled = effect.DirectionalLight2DiffuseIntensity > 0 ? true : false;
                e.DirectionalLight2.SpecularColor = effect.DirectionalLight2SpecularColor.ToVector3();
            }

            m_effect = e;
#else

            if (effect.UseSceneParameters)
            {
                if (render.EffectMgr.PerPixelLighteningEnabled)
                    m_effect.CurrentTechnique = m_effect.Techniques[m_techniquePrefix + "PixelLightBasic"];
                else
                    m_effect.CurrentTechnique = m_effect.Techniques[m_techniquePrefix + "VertexLightBasic"];
                lighteningEnabled = render.EffectMgr.LighteningEnabled;
            }
            else
            {
                if (effect.PerPixelLighteningEnabled)
                    m_effect.CurrentTechnique = m_effect.Techniques[m_techniquePrefix + "PixelLightBasic"];
                else
                    m_effect.CurrentTechnique = m_effect.Techniques[m_techniquePrefix + "VertexLightBasic"];
                lighteningEnabled = effect.LighteningEnabled;
            }
            m_effect.Parameters["ViewProjection"].SetValue(effect.View * effect.Projection);
            m_effect.Parameters["World"].SetValue(effect.World);
            m_effect.Parameters["Tiles"].SetValue(effect.ColorMapTiles);
            m_effect.Parameters["Offset"].SetValue(effect.ColorMapOffset);
            m_effect.Parameters["ColorMap"].SetValue(effect.ColorMap);
            m_effect.Parameters["Alpha"].SetValue(effect.Alpha);
            m_effect.Parameters["EmissiveLight"].SetValue(new Vector4(effect.EmissiveLightColor.ToVector3(), effect.EmissiveLightIntensity));
            m_effect.Parameters["Brightness"].SetValue(effect.Brighteness);
            m_effect.Parameters["EyePosition"].SetValue(effect.EyePosition);
            if (lighteningEnabled)
            {
                if (effect.UseSceneParameters)
                {
                    var effectMgr = render.EffectMgr;
                    m_effect.Parameters["AmbientLight"].SetValue(new Vector4(effectMgr.AmbientLightColor.ToVector3(), effectMgr.AmbientLightIntensity));
                    m_effect.Parameters["DirectionalLight1Direction"].SetValue(effectMgr.DirectionalLight1Direction);
                    m_effect.Parameters["DirectionalLight1Diffuse"].SetValue(new Vector4(effectMgr.DirectionalLight1DiffuseColor.ToVector3(), effectMgr.DirectionalLight1DiffuseIntensity));
                    m_effect.Parameters["DirectionalLight1Specular"].SetValue(new Vector4(effectMgr.DirectionalLight1SpecularColor.ToVector3(), effectMgr.DirectionalLight1SpecularIntensity));
                    m_effect.Parameters["DirectionalLight2Direction"].SetValue(effectMgr.DirectionalLight2Direction);
                    m_effect.Parameters["DirectionalLight2Diffuse"].SetValue(new Vector4(effectMgr.DirectionalLight2DiffuseColor.ToVector3(), effectMgr.DirectionalLight2DiffuseIntensity));
                    m_effect.Parameters["DirectionalLight2Specular"].SetValue(new Vector4(effectMgr.DirectionalLight2SpecularColor.ToVector3(), effectMgr.DirectionalLight2SpecularIntensity));
                    m_effect.Parameters["DirectionalLight0Direction"].SetValue(effectMgr.DirectionalLight0Direction);
                    m_effect.Parameters["DirectionalLight0Diffuse"].SetValue(new Vector4(effectMgr.DirectionalLight0DiffuseColor.ToVector3(), effectMgr.DirectionalLight0DiffuseIntensity));
                    m_effect.Parameters["DirectionalLight0Specular"].SetValue(new Vector4(effectMgr.DirectionalLight0SpecularColor.ToVector3(), effectMgr.DirectionalLight0SpecularIntensity));
                }
                else
                {
                    m_effect.Parameters["AmbientLight"].SetValue(new Vector4(effect.AmbientLightColor.ToVector3(), effect.AmbientLightIntensity));
                    m_effect.Parameters["DirectionalLight1Direction"].SetValue(effect.DirectionalLight1Direction);
                    m_effect.Parameters["DirectionalLight1Diffuse"].SetValue(new Vector4(effect.DirectionalLight1DiffuseColor.ToVector3(), effect.DirectionalLight1DiffuseIntensity));
                    m_effect.Parameters["DirectionalLight1Specular"].SetValue(new Vector4(effect.DirectionalLight1SpecularColor.ToVector3(), effect.DirectionalLight1SpecularIntensity));
                    m_effect.Parameters["DirectionalLight2Direction"].SetValue(effect.DirectionalLight2Direction);
                    m_effect.Parameters["DirectionalLight2Diffuse"].SetValue(new Vector4(effect.DirectionalLight2DiffuseColor.ToVector3(), effect.DirectionalLight2DiffuseIntensity));
                    m_effect.Parameters["DirectionalLight2Specular"].SetValue(new Vector4(effect.DirectionalLight2SpecularColor.ToVector3(), effect.DirectionalLight2SpecularIntensity));
                    m_effect.Parameters["DirectionalLight0Direction"].SetValue(effect.DirectionalLight0Direction);
                    m_effect.Parameters["DirectionalLight0Diffuse"].SetValue(new Vector4(effect.DirectionalLight0DiffuseColor.ToVector3(), effect.DirectionalLight0DiffuseIntensity));
                    m_effect.Parameters["DirectionalLight0Specular"].SetValue(new Vector4(effect.DirectionalLight0SpecularColor.ToVector3(), effect.DirectionalLight0SpecularIntensity));
                }
            }
            else
            {
                m_effect.Parameters["AmbientLight"].SetValue(Vector4.Zero);// new Vector4(0, 0, 0, 0));
                m_effect.Parameters["DirectionalLight1Direction"].SetValue(Vector3.Zero); // new Vector3(0, 0, 0));
                m_effect.Parameters["DirectionalLight1Diffuse"].SetValue(Vector4.Zero);  //(new Vector4(0, 0, 0, 0));
                m_effect.Parameters["DirectionalLight1Specular"].SetValue(Vector4.Zero);  //(new Vector4(0, 0, 0, 0));
                m_effect.Parameters["DirectionalLight2Direction"].SetValue(Vector3.Zero); //new Vector3(0, 0, 0));
                m_effect.Parameters["DirectionalLight2Diffuse"].SetValue(Vector4.Zero);  //(new Vector4(0, 0, 0, 0));
                m_effect.Parameters["DirectionalLight2Specular"].SetValue(Vector4.Zero);  //(new Vector4(0, 0, 0, 0));
                m_effect.Parameters["DirectionalLight0Direction"].SetValue(Vector3.Zero); //new Vector3(0, 0, 0));
                m_effect.Parameters["DirectionalLight0Diffuse"].SetValue(Vector4.Zero);  //(new Vector4(0, 0, 0, 0));
                m_effect.Parameters["DirectionalLight0Specular"].SetValue(Vector4.Zero);  //(new Vector4(0, 0, 0, 0));
            }
#endif
            return this;
        }


        #endregion
    }
}
